package com.njuse.jvmfinal.Instruction;

import java.nio.ByteBuffer;

import com.njuse.jvmfinal.memory.jclass.JClass;
import com.njuse.jvmfinal.memory.jclass.runtimeConstantPool.constant.Constant;
import com.njuse.jvmfinal.memory.jclass.runtimeConstantPool.constant.ref.ClassRef;
import com.njuse.jvmfinal.runtimestructure.Jarray;
import com.njuse.jvmfinal.runtimestructure.Jframe;
import com.njuse.jvmfinal.runtimestructure.Jobject;

public class INSTANCEOF extends Instruction {
	private int index;
	public void readindex(ByteBuffer reader) {
		this.index=(int)reader.getShort();
	}
	
	public void execute(Jframe frame) {
		Constant classref=frame.getMymethod().getClazz().getRuntimeConstantPool().getConstant(index);
		ClassRef clazzref=(ClassRef) classref;
		JClass T=clazzref.getclass();
		Object[] stack=frame.getManagestack();
		int top=frame.getStacktop();
		Object S=stack[top-1];
		top--;
		
		if (S==null) {
			stack[top]=0;
			top++;
			frame.setManagestack(stack);
			frame.setStacktop(top);
			return;
		}
		
		if (S.getClass().getName().contains("Jobject")) {
			Jobject ref=(Jobject) S;
			JClass clazz=ref.getClazz();
			JClass temp=clazz;
			int flag=0;
			while (temp!=null) {
				if (temp==T) flag=1;
				temp=temp.getSuperClass();
			}
			if (flag==1) {
				stack[top]=1;
				top++;
				frame.setManagestack(stack);
				frame.setStacktop(top);
				return;
			}
			JClass[] interfaces=clazz.getInterfaces();
			for (int i=0;i<interfaces.length;i++) {
				if (interfaces[i]==T) {
					stack[top]=1;
					top++;
					frame.setManagestack(stack);
					frame.setStacktop(top);
					return;
				}
			}
		
			stack[top]=0;
			top++;
			frame.setManagestack(stack);
			frame.setStacktop(top);
			return;
		}
		
		if (S.getClass().getName().contains("Jarray")) {
			
			if (T.isIsarray()==false) {
				if (T.getName().contains("java/lang/Object")||T.getName().contains("Cloneable")||T.getName().contains("Serializable")) {
					stack[top]=1;
					top++;
					frame.setManagestack(stack);
					frame.setStacktop(top);
					return;
				}else {
					stack[top]=0;
					top++;
					frame.setManagestack(stack);
					frame.setStacktop(top);				
					return;
				}
			}else {
				Jarray array=(Jarray) S;
				String name=T.getName();
				int flag=0;
				if (name.contains("[I")) {
					if (array.getFlag()==10) flag=1;
				}
				if (name.contains("[J")) {
					if (array.getFlag()==11) flag=1;
				}
				if (name.contains("[S")) {
					if (array.getFlag()==9) flag=1;
				}
				if (name.contains("[B")) {
					if (array.getFlag()==8) flag=1;
				}
				if (name.contains("[D")) {
					if (array.getFlag()==7) flag=1;
				}
				if (name.contains("[F")) {
					if (array.getFlag()==6) flag=1;
				}
				if (name.contains("[C")) {
					if (array.getFlag()==5) flag=1;
				}
				if (name.contains("[Z")) {
					if (array.getFlag()==4) flag=1;
				}
               if (flag==0) {		
				stack[top]=0;
				top++;
				frame.setManagestack(stack);
				frame.setStacktop(top);
				return;	
               }else {
   				stack[top]=1;
   				top++;
   				frame.setManagestack(stack);
   				frame.setStacktop(top);
   				return;	  
               }
			}
		}
				
	}
	
}
